package com.sapitest.utils.redis;

import com.sapitest.utils.ConfigFile;
import com.sapitest.utils.bean.RedisConnInfo;
import com.sapitest.utils.redis.commands.*;
import org.testng.Reporter;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

import java.util.Arrays;
import java.util.List;

/**
 * @date 2019-01-13
 * @author Liuxu
 * @version 1.0.0
 * @since jdk1.8
 */
@Deprecated
public class RedisUtil {

    private static int MAX_TOTAL = Integer.parseInt(ConfigFile.getSystemParameter("redis_max_total"));
    private static int MAX_IDLE = Integer.parseInt(ConfigFile.getSystemParameter("redis_max_idle"));
    private static int MAX_WAIT = Integer.parseInt(ConfigFile.getSystemParameter("redis_max_wait_millis"));
    private static int CONNECT_TIMEOUT = Integer.parseInt(ConfigFile.getSystemParameter("redis_connect_timeout"));
    private static boolean TEST_ON_BORROW = Boolean.parseBoolean(ConfigFile.getSystemParameter("redis_test_on_borrow"));
    private static boolean TEST_ON_RETURN = Boolean.parseBoolean(ConfigFile.getSystemParameter("redis_test_on_return"));

    private static Jedis jedis = null;

    private RedisUtil(RedisConnInfo redisConnInfo){
        JedisPoolConfig config = new JedisPoolConfig();
        config.setMaxTotal(MAX_TOTAL);
        config.setMaxIdle(MAX_IDLE);
        config.setMaxWaitMillis(MAX_WAIT);
        config.setTestOnBorrow(TEST_ON_BORROW);
        config.setTestOnReturn(TEST_ON_RETURN);
        JedisPool jedisPool = new JedisPool(config, redisConnInfo.getHost(), redisConnInfo.getPort(), CONNECT_TIMEOUT, redisConnInfo.getPassword());
        jedis = jedisPool.getResource();
    }

    /**
     * Redis工具类实例化
     * @param host  redis ip
     * @param pwd   redis 密码
     * @param port  redis 端口
     * @return  Redis工具类对象
     */
    public static RedisUtil newInstance(String host, String pwd, int port){
        RedisConnInfo redisConnInfo = new RedisConnInfo(host, pwd, port);
        return new RedisUtil(redisConnInfo);
    }

    /**
     * 关闭连接池
     */
    public void closeJedisPool() {
        try {
            jedis.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 将命令以空格分隔成List
     * @param commands 执行的redis命令
     * @return 命令的列表
     */
    private List getCommand(String commands){
        return Arrays.asList(commands.split(" "));
    }

    /**
     * 执行key类型的redis命令，并将结果以字符串返回
     * @param commands 执行的redis命令
     * @return String
     */
    public String execKeyCommand(String commands){
        RedisKey rk = new RedisKey();
        List list = getCommand(commands);
        try {
            switch (list.get(0).toString().toUpperCase()){
                case "DEL":
                    return rk.kvdel(jedis, String.valueOf(list.get(1)));
                case "EXISTS":
                    return rk.kvexists(jedis, String.valueOf(list.get(1)));
                case "EXPIRE":
                    return rk.kvexpire(jedis, String.valueOf(list.get(1)), Integer.valueOf(String.valueOf(list.get(2))));
                case "EXPIREAT":
                    return rk.kvexpireAt(jedis, String.valueOf(list.get(1)), Long.valueOf(String.valueOf(list.get(2))));
                case "SORT":
                    return rk.kvsort(jedis, String.valueOf(list.get(1)));
                case "TTL":
                    return rk.kvttl(jedis, String.valueOf(list.get(1)));
                case "PERSIST":
                    return rk.kvpersist(jedis, String.valueOf(list.get(1)));
                default:
                    Reporter.log("【ERROR】不支持的命令！", true);
                    break;
            }
        } catch (NumberFormatException e) {
            Reporter.log("【ERROR】NumberFormatException. Please check commands.", true);
        } catch (ArrayIndexOutOfBoundsException ignored){
            Reporter.log("【ERROR】ArrayIndexOutOfBoundsException. Please check commands.", true);
        } catch (Exception ignored){
            Reporter.log("【ERROR】Unknown error. Please check commands.", true);
        }
        return "";
    }

    /**
     * 执行String类型的redis命令，并将结果以字符串返回
     * @param commands 执行的redis命令
     * @return String
     */
    public String execStringCommand(String commands){
        RedisString rs = new RedisString();
        List list = getCommand(commands);
        try {
            switch (list.get(0).toString().toUpperCase()){
                case "GET":
                    return rs.stget(jedis, String.valueOf(list.get(1)));
                case "SET":
                    return rs.stset(jedis, String.valueOf(list.get(1)), String.valueOf(list.get(2)));
                case "APPEND":
                    return rs.stappend(jedis, String.valueOf(list.get(1)), String.valueOf(list.get(2)));
                case "BITCOUNT":
                    return rs.stbitcount(jedis, String.valueOf(list.get(1)));
                case "DERC":
                    return rs.stdecr(jedis, String.valueOf(list.get(1)));
                case "DERCBY":
                    return rs.stdecrby(jedis, String.valueOf(list.get(1)), Long.valueOf(String.valueOf(list.get(2))));
                case "INCR":
                    return rs.stincr(jedis, String.valueOf(list.get(1)));
                case "INCRBY":
                    return rs.stincrby(jedis, String.valueOf(list.get(1)), Long.valueOf(String.valueOf(list.get(2))));
                default:
                    Reporter.log("【ERROR】不支持的命令！", true);
                    break;
            }
        } catch (NumberFormatException e) {
            Reporter.log("【ERROR】NumberFormatException. Please check commands.", true);
        } catch (ArrayIndexOutOfBoundsException ignored){
            Reporter.log("【ERROR】ArrayIndexOutOfBoundsException. Please check commands.", true);
        } catch (Exception ignored){
            Reporter.log("【ERROR】Unknown error. Please check commands.", true);
        }
        return "";
    }

    /**
     * 执行Hash类型的redis命令，并将结果以字符串返回
     * @param commands 执行的redis命令
     * @return String
     */
    public String execHashCommand(String commands){
        RedisHash rh = new RedisHash();
        List list = getCommand(commands);
        try {
            switch (list.get(0).toString().toUpperCase()){
                case "HDEL":
                    return rh.hshdel(jedis, String.valueOf(list.get(1)));
                case "HGET":
                    return rh.hshget(jedis, String.valueOf(list.get(1)), String.valueOf(list.get(2)));
                case "HEXISTS":
                    return rh.hshexists(jedis, String.valueOf(list.get(1)), String.valueOf(list.get(2)));
                case "HGETALL":
                    return rh.hshgetall(jedis, String.valueOf(list.get(1)));
                case "HINCRBY":
                    return rh.hshincrby(jedis, String.valueOf(list.get(1)), String.valueOf(list.get(2)), Long.valueOf(String.valueOf(list.get(2))));
                case "HINCRBYFLOAT":
                    return rh.hshincrbyfloat(jedis, String.valueOf(list.get(1)), String.valueOf(list.get(2)), Float.valueOf(String.valueOf(list.get(2))));
                case "HKEYS":
                    return rh.hshkeys(jedis, String.valueOf(list.get(1)));
                case "HLEN":
                    return rh.hshlen(jedis, String.valueOf(list.get(1)));
                case "HSET":
                    return rh.hshset(jedis, String.valueOf(list.get(1)), String.valueOf(list.get(2)), String.valueOf(list.get(3)));
                default:
                    Reporter.log("【ERROR】不支持的命令！", true);
                    break;
            }
        } catch (NumberFormatException e) {
            Reporter.log("【ERROR】NumberFormatException. Please check commands.", true);
        } catch (ArrayIndexOutOfBoundsException ignored){
            Reporter.log("【ERROR】ArrayIndexOutOfBoundsException. Please check commands.", true);
        } catch (Exception ignored){
            Reporter.log("【ERROR】Unknown error. Please check commands.", true);
        }
        return "";
    }

    /**
     * 执行List类型的redis命令，并将结果以字符串返回
     * @param commands 执行的redis命令
     * @return String
     */
    public String execListCommand(String commands){
        RedisList rl = new RedisList();
        List list = getCommand(commands);
        try {
            switch (list.get(0).toString().toUpperCase()){
                case "LLEN":
                    return rl.lsllen(jedis, String.valueOf(list.get(1)));
                case "LINDEX":
                    return rl.lslindex(jedis, String.valueOf(list.get(1)), Long.valueOf(String.valueOf(list.get(2))));
                case "LPUSH":
                    return rl.lslpush(jedis, String.valueOf(list.get(1)), String.valueOf(list.get(2)));
                case "LRANGE":
                    return rl.lslrange(jedis, String.valueOf(list.get(1)), Long.valueOf(String.valueOf(list.get(2))), Long.valueOf(String.valueOf(list.get(3))));
                case "RPUSH":
                    return rl.lsrpush(jedis, String.valueOf(list.get(1)), String.valueOf(list.get(2)));
                default:
                    Reporter.log("【ERROR】不支持的命令！", true);
                    break;
            }
        } catch (NumberFormatException e) {
            Reporter.log("【ERROR】NumberFormatException. Please check commands.", true);
        } catch (ArrayIndexOutOfBoundsException ignored){
            Reporter.log("【ERROR】ArrayIndexOutOfBoundsException. Please check commands.", true);
        } catch (Exception ignored){
            Reporter.log("【ERROR】Unknown error. Please check commands.", true);
        }
        return "";
    }

    /**
     * 执行Set类型的redis命令，并将结果以字符串返回
     * @param commands 执行的redis命令
     * @return String
     */
    public String execSetCommand(String commands){
        RedisSet rs = new RedisSet();
        List list = getCommand(commands);
        try {
            switch (list.get(0).toString().toUpperCase()){
                case "SANN":
                    return rs.setsadd(jedis, String.valueOf(list.get(1)), String.valueOf(list.get(2)));
                case "SCARD":
                    return rs.setscard(jedis, String.valueOf(list.get(1)));
                case "SRANDMEMBER":
                    return rs.setsrandmember(jedis, String.valueOf(list.get(1)), Integer.valueOf(String.valueOf(list.get(2))));
                case "SMEMBERS":
                    return rs.setsmembers(jedis, String.valueOf(list.get(1)));
                case "SISMEMBER":
                    return rs.setsismember(jedis, String.valueOf(list.get(1)), String.valueOf(list.get(2)));
                default:
                    Reporter.log("【ERROR】不支持的命令！", true);
                    break;
            }
        } catch (NumberFormatException e) {
            Reporter.log("【ERROR】NumberFormatException. Please check commands.", true);
        } catch (ArrayIndexOutOfBoundsException ignored){
            Reporter.log("【ERROR】ArrayIndexOutOfBoundsException. Please check commands.", true);
        } catch (Exception ignored){
            Reporter.log("【ERROR】Unknown error. Please check commands.", true);
        }
        return "";
    }

    /**
     * 执行Server类型的redis命令，并将结果以字符串返回
     * @param commands 执行的redis命令
     * @return String
     */
    public String execServerCommand(String commands){
        RedisServer rs = new RedisServer();
        List list = getCommand(commands);
        try {
            switch (list.get(0).toString().toUpperCase()){
                case "SANN":
                    return rs.svflushdb(jedis);
                case "SCARD":
                    return rs.svdbsize(jedis);
                default:
                    Reporter.log("【ERROR】不支持的命令！", true);
                    break;
            }
        } catch (NumberFormatException e) {
            Reporter.log("【ERROR】NumberFormatException. Please check commands.", true);
        } catch (ArrayIndexOutOfBoundsException ignored){
            Reporter.log("【ERROR】ArrayIndexOutOfBoundsException. Please check commands.", true);
        } catch (Exception ignored){
            Reporter.log("【ERROR】Unknown error. Please check commands.", true);
        }
        return "";
    }

    /**
     * 执行SortedSet类型的redis命令，并将结果以字符串返回
     * @param commands 执行的redis命令
     * @return String
     */
    public String execSortedSetCommand(String commands){
        RedisSortedSet rs = new RedisSortedSet();
        List list = getCommand(commands);
        try {
            switch (list.get(0).toString().toUpperCase()){
                case "ZADD":
                    return rs.sszadd(jedis, String.valueOf(list.get(1)), Double.valueOf(String.valueOf(list.get(2))), String.valueOf(list.get(3)));
                case "ZCARD":
                    return rs.sszcard(jedis, String.valueOf(list.get(1)));
                case "ZCOUNT":
                    return rs.sszcount(jedis, String.valueOf(list.get(1)), Double.valueOf(String.valueOf(list.get(2))), Double.valueOf(String.valueOf(list.get(3))));
                case "ZRANGE":
                    return rs.sszrange(jedis, String.valueOf(list.get(1)), Long.valueOf(String.valueOf(list.get(2))), Long.valueOf(String.valueOf(list.get(3))));
                case "ZRANGEBYSCOPE":
                    return rs.sszrangebyscope(jedis, String.valueOf(list.get(1)), String.valueOf(list.get(2)), String.valueOf(list.get(3)));
                case "ZRANK":
                    return rs.sszrank(jedis, String.valueOf(list.get(1)), String.valueOf(list.get(2)));
                case "ZREVRANGE":
                    return rs.sszrevrange(jedis, String.valueOf(list.get(1)), Long.valueOf(String.valueOf(list.get(2))), Long.valueOf(String.valueOf(list.get(3))));
                case "ZREVRANGEBYSCOPE":
                    return rs.sszrevrangebyscope(jedis, String.valueOf(list.get(1)), String.valueOf(list.get(2)), String.valueOf(list.get(3)));
                case "ZREVRANK":
                    return rs.sszrevrank(jedis, String.valueOf(list.get(1)), String.valueOf(list.get(2)));
                case "ZSCOPE":
                    return rs.sszscope(jedis, String.valueOf(list.get(1)), String.valueOf(list.get(2)));
                default:
                    Reporter.log("【ERROR】不支持的命令！", true);
                    break;
            }
        } catch (NumberFormatException e) {
            Reporter.log("【ERROR】NumberFormatException. Please check commands.", true);
        } catch (ArrayIndexOutOfBoundsException ignored){
            Reporter.log("【ERROR】ArrayIndexOutOfBoundsException. Please check commands.", true);
        } catch (Exception ignored){
            Reporter.log("【ERROR】Unknown error. Please check commands.", true);
        }
        return "";
    }
}
